package coroutines.coroutine

import coroutines.coroutine.CreateCoroutineWithReceiverTest.Companion.createCoroutine
import coroutines.coroutine.CreateCoroutineWithReceiverTest.Companion.launchCoroutine
import kotlinx.coroutines.delay
import kotlin.coroutines.*

class CreateCoroutineWithReceiverTest<T> {
    companion object {
        fun<R, T> createCoroutine(receiver:R, block:suspend R.()->T):Continuation<Unit> {
            return block.createCoroutine(receiver, object:Continuation<T> {
                override val context = EmptyCoroutineContext

                override fun resumeWith(result: Result<T>) {
                    println("crateContinuation() resumeWith(${result.getOrNull()})")
                }
            })
        }

        fun <R, T> launchCoroutine(receiver: R, block: suspend R.() -> T) {
            block.startCoroutine(receiver, object : Continuation<T> {
                override val context = EmptyCoroutineContext

                override fun resumeWith(result: Result<T>) {
                    println("launchCoroutine() resumeWith(${result.getOrNull()})")
                }
            })
        }
    }

    suspend fun produce(value: T) {
        println("produce($value)")
    }

}

fun main() {
    val continuation  = createCoroutine(CreateCoroutineWithReceiverTest<String>()) {
        println("launchCoroutine(CreateCoroutineWithReceiverTest) start")

        produce("Bilibili")

        produce("哔哩哔哩")
    }

    continuation.resume(Unit)


    try {
        launchCoroutine(CreateCoroutineWithReceiverTest<Int>()) {
            println("launchCoroutine(CreateCoroutineWithReceiverTest) start")

            produce(2233)

            try {
                delay(1000)
            } catch (t: Throwable) {
                println("launchCoroutine error: ${t.message}")
                t.printStackTrace()
            }

            produce(1024)
        }
    } catch (t: Throwable) {
        println("main error: ${t.message}")
    }
}